package k3.media
{
	import flash.display.Stage;
	import flash.events.*;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	import flash.events.NetStatusEvent;
	import flash.geom.Rectangle;
	import flash.media.SoundTransform;
	import flash.media.StageVideo;
	import flash.media.StageVideoAvailability;
	import flash.media.Video;
	import flash.net.NetConnection;
	import flash.net.NetStream;
	
	import k3.event.KEvent;
	
	/**
	 * ...
	 * @author FireKnight
	 */
	public class VideoManager extends EventDispatcher
	{
		private var ns:NetStream;
		private var nc:NetConnection;
		private var video:Video;
		private var movie_url:String;
		private var duration:Number;
		private var soundTrans:SoundTransform=new SoundTransform();
		private var volumn:Number;
		
		
		/**
		 * Dispatched when it is ready to play the video
		 *
		 * @eventType CONNECTION_READY
		 */
		public static const CONNECTION_READY:String = "CONNECTION_READY";
		
		/**
		 * Dispatched when the MetaData is ready
		 *
		 * @eventType METADATA_READY
		 */
		public static const METADATA_READY:String = "METADATA_READY";
		
		/**
		 * Dispatched when the cue point occurs.
		 *
		 * @eventType CUE_POINT
		 */
		public static const CUE_POINT:String = "CUE_POINT";
		
		/**
		 * Dispatched when the player state changes. (UNSTARTED = -1, ENDED = 0, PLAYING = 1, PAUSED = 2)
		 *
		 * @eventType PLAYER_STATE_CHANGED
		 */
		public static const PLAYER_STATE_CHANGED:String = "PLAYER_STATE_CHANGED";
		
		public static const UNSTARTED:int = -1;
		public static const ENDED:int = 0;
		public static const PLAYING:int = 1;
		public static const PAUSED:int = 2;
		
		protected var _state:int;
		protected var _duration:Number;
		protected var _metaDataInfo:Object;
		protected var _cuePointInfo:Object;
		public function VideoManager( target:IEventDispatcher=null)
		{
			super(target);
			trace("VideoManager 2019.11.01 build 3");
		}
		
		
		/**
		 * Get the bytes loaded of the video
		 */
		public function getVideoBytesLoaded():Number {
			var bytesLoaded:Number = 0;
			if (ns) {
				bytesLoaded = ns.bytesLoaded;
			}
			return bytesLoaded;
		}
		
		/**
		 * Get the bytes total of the video
		 */
		public function getVideoBytesTotal():Number {
			var bytesTotal:Number = 0;
			if (ns) {
				bytesTotal = ns.bytesTotal;
			}
			return bytesTotal;
		}
		/**
		 * Get the state of the video player
		 * (UNSTARTED = -1, ENDED = 0, PLAYING = 1, PAUSED = 2)
		 */
		public function getPlayerState():Number {
			// Returns the state of the player. Possible values are unstarted (-1), ended (0), playing (1), paused (2).
			return _state;
		}

		public function showMovie(s:String,yl:Number=1):void
		{
			trace("showMovie,"+s,yl);
			movie_url=s;
		
			if (nc) {
				nc.close();
				nc.removeEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
				nc.removeEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);
			}
			setPlayerState(UNSTARTED);
			volumn=yl;
			nc = new NetConnection();
			var clientObj:Object = new Object();
			clientObj.onBWDone = onBWDone;
			nc.client = clientObj;
			nc.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler, false, 0, true);
			nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler, false, 0, true);

			nc.connect(null);
			
			
		}
		
		protected function connectStream():void {
			trace("connectStream");
			if (ns) {
				ns.close();
				ns.removeEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
			}
			ns = new NetStream(nc);
			ns.addEventListener(NetStatusEvent.NET_STATUS, netStatusHandler, false, 0, true);
			var clientObj:Object = new Object();
			clientObj.onMetaData = onMetaData;
			clientObj.onCuePoint = onCuePoint;
			ns.client = clientObj;
			
			soundTrans.volume=volumn;
			ns.soundTransform=soundTrans;
			ns.bufferTime=3;
			ns.bufferTimeMax=30;
			ns.maxPauseBufferTime=120;
			ns.step(1);
		
			if(video)
			{
				video.clear();
			}
			video = new Video();
			video.smoothing=true;
			video.attachNetStream(ns);
			dispatchEvent(new KEvent(CONNECTION_READY));
			
		    play();
		}
		
		protected function netStatusHandler(event:NetStatusEvent):void {
			switch (event.info.code) {
				case "NetConnection.Connect.Success":
					connectStream();
					break;
				case "NetStream.Play.Stop":
					if (  uint(duration)==uint(ns.time)&&(duration>0&&ns.time>0))
					{
						trace("播放完了,"+event.info.code);
						//this.dispatchEvent(new KEvent("playEnd"));
					
						setPlayerState(ENDED);
						dispatchEvent(new KEvent(PLAYER_STATE_CHANGED));
					}
					break;
				case "NetStream.Play.StreamNotFound":
					trace("Stream not found" );
					break;
				default :
					break;
			}
		}
		
		protected function securityErrorHandler(event:SecurityErrorEvent):void {
			trace("securityErrorHandler: " + event);
		}
		protected function setPlayerState(value:int):void {
			// Possible values are unstarted (-1), ended (0), playing (1), paused (2).
			_state = value;
			dispatchEvent(new KEvent(PLAYER_STATE_CHANGED));
		}

		
		
		protected function onCuePoint(info:Object):void {
			trace("cuepoint: time=" + info.time + " name=" + info.name + " type=" + info.type);
			_cuePointInfo = info;
			dispatchEvent(new KEvent(CUE_POINT));
		}
		
		protected function onBWDone(info:Object = null):void {
			trace("onBWDone");
		}
		
		public function onPlayStatus( info:Object ):void{ 
			switch ( info.code ){ 
				case "NetStream.Play.Switch": 
					break; 
				case "NetStream.Play.Complete": 
					trace("Complete"); 
					break; 
				default: 
					for ( var a:String in info ) {  
						trace(a + " " + info[a]); 
					} 
					break; 
			} 
		} 
		
		private function clearVideo():void
		{
			if(video)
			{
				video.clear();
				video = null;
			}
			cleartStream();
		}
		
		private function cleartStream():void
		{
			ns.removeEventListener(NetStatusEvent.NET_STATUS, netStatusHandler);
			ns.dispose();
			nc.close();
			ns = null;
			nc = null;
		}
		

		
		public function onMetaData(infoObject:Object):void
		{
//			trace("////onMetaData////");
//			Analyzer.start(infoObject);
//			trace("////onMetaData end////");
			trace("影片有"+infoObject.duration+"秒");
			trace("metadata: duration=" + infoObject.duration + " width=" + infoObject.width + " height=" + infoObject.height + " framerate=" + infoObject.framerate);
			duration=infoObject.duration;
			this.dispatchEvent(new KEvent(METADATA_READY,{width:infoObject.width,height:infoObject.height,duration:infoObject.duration}));
		}
		
		public function onXMPData(infoObject:Object):void
		{
			//trace("////onXMPData////");
			////Analyzer.start(infoObject);
			//trace("////onXMPData end////");
		}
		
		/*private function statusHandler(e:NetStatusEvent):void
		{
			
			if (e.info.code == "NetStream.Play.Complete")
			{
				trace("播放完了,"+e.info.code);
				this.dispatchEvent(new KEvent("playEnd"));
			}
			else if(e.info.code=="NetStream.Play.Stop" && uint(duration)==uint(ns.time)&&(duration>0&&ns.time>0))
			{
				trace("播放完了,"+e.info.code);
				this.dispatchEvent(new KEvent("playEnd"));
			}
			else if(e.info.code=="NetStream.Buffer.Empty")
			{
				trace("缓存不足,"+e.info.code);
				this.dispatchEvent(new KEvent("BufferEmpty"));
			}
			else if(e.info.code=="NetStream.Buffer.Full")
			{
				trace("缓存充足,"+e.info.code);
				this.dispatchEvent(new KEvent("BufferFull"));
			}

		}*/
	
		
		public function stop():void
		{
			ns.close();	
			trace("close");
		}
		
		
		public function pause():void
		{
			if (ns) {
				trace("pauseVideo");
				ns.pause();
				setPlayerState(PAUSED);
			}
		}
		
		public function resume():void
		{
			ns.resume();
			trace("resume");
			setPlayerState(PLAYING);
		}
		
		public function play():void
		{
			if (_state == UNSTARTED) {
				trace("ns was null, loading video");
				ns.play(movie_url);
			} else {
				trace("resume");
				ns.resume();
			}
			setPlayerState(PLAYING);
		
	
		}
		
		public function setVolume(s:Number):void
		{
			soundTrans.volume=s;
			ns.soundTransform=soundTrans;
		}
		
		public function gotoAndPlay(s:uint):void
		{
			ns.seek(s);
		}
		
		public function get _video():Video
		{
			return video;
		}
		
		public function onTimeCoordInfo(obj:*=null):void
		{
			
		}
		
		private function onAsyncErrorHandler(evt:AsyncErrorEvent):void{};
		
		public function get totalTime():Number
		{
			return duration;
		}
		
		public function gc():void
		{
			clearVideo();
		}
		
		public function get time():Number
		{
			if(ns)
			{
				return ns.time;
			}
			else
			{
				return 0;
			}
		}
	
	}

}